home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 February: Tool Chest / Dev.CD Feb 95 / Dev.CD Feb 95.toast / Tool Chest / Development Tools & Languages / Dylan Related / Mindy-1.1 (sources only) / mindy-1.1 / comp / mindycomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-28  |  6.5 KB  |  302 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: mindycomp.c,v 1.8 94/06/27 16:49:37 wlott Exp $
  27. *
  28. * This file is the main driver.
  29. *
  30. \**********************************************************************/
  31.  
  32. #include <stdio.h>
  33. #include <stdarg.h>
  34. #include <string.h>
  35.  
  36. #include "mindycomp.h"
  37. #include "parser.h"
  38. #include "src.h"
  39. #include "print.h"
  40. #include "expand.h"
  41. #include "envanal.h"
  42. #include "lexer.h"
  43. #include "header.h"
  44. #include "sym.h"
  45. #include "info.h"
  46. #include "compile.h"
  47. #include "dump.h"
  48.  
  49. struct body *Program = NULL;
  50.  
  51. struct symbol *LibraryName = NULL;
  52. struct symbol *ModuleName = NULL;
  53. boolean ParseOnly = FALSE;
  54.  
  55. char *current_file = "<stdin>";
  56.  
  57. static int nerrors = 0;
  58.  
  59. void error(int line, char *msg, ...)
  60. {
  61.     va_list ap;
  62.  
  63.     fprintf(stderr, "%s:%d: error: ", current_file, line);
  64.     va_start(ap, msg);
  65.     vfprintf(stderr, msg, ap);
  66.     va_end(ap);
  67.     if (msg[strlen(msg)-1] != '\n')
  68.     putc('\n', stderr);
  69.  
  70.     nerrors++;
  71. }
  72.  
  73. void warn(int line, char *msg, ...)
  74. {
  75.     va_list ap;
  76.  
  77.     fprintf(stderr, "%s:%d: warning: ", current_file, line);
  78.     va_start(ap, msg);
  79.     vfprintf(stderr, msg, ap);
  80.     va_end(ap);
  81.     if (msg[strlen(msg)-1] != '\n')
  82.     putc('\n', stderr);
  83. }
  84.  
  85.  
  86. static void usage(void)
  87. {
  88.     fprintf(stderr, "usage: mindycomp [-d[p][e]] [-l library-name] "
  89.         "[-o object-name] [-p] source-name\n");
  90.     exit(1);
  91. }
  92.  
  93. static void set_module(char *value)
  94. {
  95.     if (ModuleName) {
  96.     fprintf(stderr, "multiple module: file headers.\n");
  97.     exit(1);
  98.     }
  99.     ModuleName = symbol(value);
  100. }
  101.  
  102. static char *find_extension(char *source)
  103. {
  104.     char *slash = strrchr(source, '/');
  105.     char *dot = strchr(slash ? slash : source, '.');
  106.  
  107.     if (dot)
  108.     return dot+1;
  109.     else
  110.     return NULL;
  111. }
  112.  
  113. static char *make_output_name(char *source, char *new_extension)
  114. {
  115.     char *extension = find_extension(source);
  116.     int base_len = extension ? extension - source - 1 : strlen(source);
  117.     char *output = malloc(base_len + strlen(new_extension) + 1);
  118.  
  119.     memcpy(output, source, base_len);
  120.     strcpy(output + base_len, new_extension);
  121.  
  122.     return output;
  123. }
  124.  
  125. void main(int argc, char *argv[])
  126. {
  127.     boolean print_parse = FALSE;
  128.     boolean print_expanded = FALSE;
  129.     char *arg;
  130.     char *source_name = NULL;
  131.     char *output_name = NULL;
  132.     FILE *file;
  133.  
  134.     add_header_handler("module", set_module);
  135.  
  136.     init_sym_table();
  137.     init_info();
  138.     init_expand();
  139.     init_compile();
  140.  
  141.     while ((arg = *++argv) != NULL) {
  142.     if (arg[0] == '-') {
  143.         switch (arg[1]) {
  144.           case 'd':
  145.         if (arg[2] == '\0') {
  146.             print_parse = TRUE;
  147.             print_expanded = TRUE;
  148.         }
  149.         else {
  150.             char *ptr;
  151.             for (ptr = arg+2; *ptr != '\0'; ptr++) {
  152.             switch (*ptr) {
  153.               case 'p':
  154.                 print_parse = TRUE;
  155.                 break;
  156.               case 'e':
  157.                 print_expanded = TRUE;
  158.                 break;
  159.               default:
  160.                 fprintf(stderr, "Invalid thing to print: ``%c''\n",
  161.                     *ptr);
  162.                 usage();
  163.             }
  164.             }
  165.         }
  166.         break;
  167.  
  168.           case 'o':
  169.         if (output_name != NULL) {
  170.             fprintf(stderr, "-o can only be used once.\n");
  171.             usage();
  172.         }
  173.         else if (arg[2] != '\0')
  174.             output_name = arg+2;
  175.         else if (*++argv == NULL) {
  176.             fprintf(stderr, "-o must be followed by the output "
  177.                 "file name.\n");
  178.             usage();
  179.         }
  180.         else
  181.             output_name = *argv;
  182.         break;
  183.  
  184.           case 'l':
  185.         if (LibraryName != NULL) {
  186.             fprintf(stderr, "-l can only be used once.\n");
  187.             usage();
  188.         }
  189.         if (arg[2] != '\0')
  190.             LibraryName = symbol(arg+2);
  191.         else if (*++argv == NULL) {
  192.             fprintf(stderr, "-l must be followed by the library "
  193.                 "name.\n");
  194.             usage();
  195.         }
  196.         else
  197.             LibraryName = symbol(*argv);
  198.         break;
  199.  
  200.           case 'p':
  201.         if (ParseOnly) {
  202.             fprintf(stderr, "-p can only be used once.\n");
  203.             usage();
  204.         }
  205.         if (arg[2] != '\0') {
  206.             fprintf(stderr, "noise after -p switch: %s\n", arg+2);
  207.             usage();
  208.         }
  209.         ParseOnly = TRUE;
  210.         break;
  211.  
  212.           default:
  213.         fprintf(stderr, "Invalid flag: ``%s''\n", arg);
  214.         usage();
  215.         }
  216.     }
  217.     else if (source_name != NULL) {
  218.         fprintf(stderr, "Too many files\n");
  219.         usage();
  220.     }
  221.     else
  222.         source_name = arg;
  223.     }
  224.  
  225.     if (source_name == NULL)
  226.     usage();
  227.  
  228.  
  229.     yyin = fopen(source_name, "r");
  230.     if (yyin == NULL) {
  231.     perror(source_name);
  232.     exit(1);
  233.     }
  234.  
  235.     /* This hack is necessary because flex ignores everything in the */
  236.     /* stdio buffer, so we can't have touched the stream before calling */
  237.     /* yyparse. */
  238.     file = fopen(source_name, "r");
  239.     read_header(file);
  240.     fseek(yyin, ftell(file), 0);
  241.     fclose(file);
  242.  
  243.     current_file = source_name;
  244.  
  245.     if (ModuleName == NULL) {
  246.     warn(line_count-1, "no module: header, assuming Dylan-User\n");
  247.     ModuleName = sym_DylanUser;
  248.     }
  249.  
  250.     yyparse();
  251.  
  252.     if (print_parse) {
  253.     printf("================ Original Parse Tree ================\n");
  254.     print_body(Program, 0);
  255.     }
  256.  
  257.     if (nerrors != 0)
  258.     exit(1);
  259.  
  260.     /* Do the various source-to-source expansions. */
  261.     expand(Program);
  262.  
  263.     if (print_expanded) {
  264.     printf("================ Expanded Parse Tree ================\n");
  265.     print_body(Program, 0);
  266.     }
  267.  
  268.     if (nerrors != 0)
  269.     exit(1);
  270.  
  271.     /* Run environment analysis */
  272.     if (!ParseOnly)
  273.     environment_analysis(Program);
  274.  
  275.     if (nerrors != 0)
  276.     exit(1);
  277.  
  278.     if (output_name == NULL)
  279.     output_name = make_output_name(source_name,
  280.                        ParseOnly ? ".parse" : ".dbc");
  281.  
  282.     file = fopen(output_name, "w");
  283.     if (file == NULL) {
  284.     perror(output_name);
  285.     exit(1);
  286.     }
  287.  
  288.     dump_setup_output(source_name, file);
  289.  
  290.     /* Generate code. */
  291.     if (ParseOnly)
  292.     dump_program(Program);
  293.     else
  294.     compile(Program);
  295.  
  296.     dump_finalize_output();
  297.  
  298.     fclose(file);
  299.  
  300.     exit(0);
  301. }
  302.